package com.zhuanzhuan.hero.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zhuanzhuan.hero.user.consts.NumConsts;
import com.zhuanzhuan.hero.user.dto.BasePageQueryDTO;
import com.zhuanzhuan.hero.user.dto.privacy.SwitchPrivacyDTO;
import com.zhuanzhuan.hero.user.entity.HeroUserInfo;
import com.zhuanzhuan.hero.user.entity.HeroUserPrivacySetup;
import com.zhuanzhuan.hero.user.enums.ExceptionMsgEnum;
import com.zhuanzhuan.hero.user.enums.PrivacyTypeEnum;
import com.zhuanzhuan.hero.user.enums.StateEnum;
import com.zhuanzhuan.hero.user.exception.BusinessException;
import com.zhuanzhuan.hero.user.helper.HeroMemberHelper;
import com.zhuanzhuan.hero.user.helper.HeroSocialHelper;
import com.zhuanzhuan.hero.user.mapper.HeroUserPrivacySetupRecordMapper;
import com.zhuanzhuan.hero.user.service.HeroUserInfoService;
import com.zhuanzhuan.hero.user.service.HeroUserPrivacySetupService;
import com.zhuanzhuan.hero.user.service.HeroUserVisitRecordService;
import com.zhuanzhuan.hero.user.service.IUserService;
import com.zhuanzhuan.hero.user.util.Assert;
import com.zhuanzhuan.hero.user.vo.PageResultWrapper;
import com.zhuanzhuan.hero.user.vo.UserItemBriefVO;
import com.zhuanzhuan.hero.user.vo.UserListItemVO;
import com.zhuanzhuan.hero.user.vo.privacy.ShowVisitRecordSwitchVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * dal Interface:HeroUserPrivacySetupRecord
 * @author hanjunjun
 * @date 2024-6-26
 */
@Service
@Slf4j
public class HeroUserPrivacySetupServiceImpl
    extends ServiceImpl<HeroUserPrivacySetupRecordMapper, HeroUserPrivacySetup>
    implements HeroUserPrivacySetupService {

    @Resource
    private HeroUserInfoService heroUserInfoService;

    @Resource
    private HeroMemberHelper heroMemberHelper;

    @Resource
    private HeroSocialHelper heroSocialHelper;

    @Resource
    private HeroUserVisitRecordService userVisitRecordService;

    @Resource
    private IUserService userService;

    @Override
    public List<HeroUserPrivacySetup> listByUid(Long fromUid, Long toUid) {
        log.info("listHeroUserPrivacySetupRecordByUid fromUid={} toUid={}", fromUid, toUid);
        HeroUserPrivacySetup query = new HeroUserPrivacySetup();
        query.setFromUid(fromUid);
        query.setToUid(toUid);
        query.setState(StateEnum.EFFECTIVE.getCode());
        return getBaseMapper().select(query);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void setupPrivacy(Long fromUid, Long toUid, Integer isInvisible, Integer isBlock) {
        log.info("setupPrivacy fromUid={},toUid={},isInvisible={},isBlock={}", fromUid, toUid, isInvisible, isBlock);
        if (fromUid.equals(toUid)) {
            log.info("uid相同");
            throw new BusinessException(ExceptionMsgEnum.PARAM_ERROR);
        }

        List<HeroUserPrivacySetup> setups = this.listByUid(fromUid, toUid);

        if (Objects.nonNull(isInvisible)) {
            log.info("设置不看ta");
            this.insertOrDel(fromUid, toUid, PrivacyTypeEnum.INVISIBLE.getCode(), NumConsts.ONE.equals(isInvisible),
                setups);
        }
        if (Objects.nonNull(isBlock)) {
            log.info("设置不让ta看");
            this.insertOrDel(fromUid, toUid, PrivacyTypeEnum.BLOCK.getCode(), NumConsts.ONE.equals(isBlock),
                setups);
        }
    }

    /**
     * 对不同的意思你类型
     * 设置开启：如果已设置则跳过，如果未设置，则插入数据
     * 设置关闭：如果已设置需要删除，如果未设置则跳过
     * @param fromUid
     * @param toUid
     * @param privacyType
     * @param openSetup
     * @param dbSetups
     * @return void
     * @author  hanjunjun
     * @date 2024/6/26
     **/
    private void insertOrDel(Long fromUid, Long toUid, Integer privacyType, boolean openSetup,
        List<HeroUserPrivacySetup> dbSetups) {
        HeroUserPrivacySetup setupRecord =
            dbSetups.stream().filter(record -> privacyType.equals(record.getPrivacyType()))
                .findFirst().orElse(null);
        if (openSetup) {
            //设置开启   如果已设置则跳过，如果未设置，则插入数据
            if (Objects.isNull(setupRecord)) {
                this.save(this.buildEntity(fromUid, toUid, privacyType));
            }
        } else  {
            //设置关闭   如果已设置需要删除，如果未设置则跳过
            if (Objects.nonNull(setupRecord)) {
                this.delById(setupRecord.getId());
            }
        }
    }

    @Override
    public void delById(Long id) {
        log.info("delHeroUserPrivacySetupById id={}", id);
        this.update(new LambdaUpdateWrapper<HeroUserPrivacySetup>()
            .set(HeroUserPrivacySetup::getState, StateEnum.IS_DELETED.getCode())
            .eq(HeroUserPrivacySetup::getId, id));
    }

    @Override
    public ShowVisitRecordSwitchVO queryShowVisitRecordSwitch(Long uid) {
        HeroUserInfo userInfo = heroUserInfoService.getUserByUid(uid);
        Assert.notNull(userInfo, ExceptionMsgEnum.BUSINESS_ERROR);

        ShowVisitRecordSwitchVO vo = new ShowVisitRecordSwitchVO();
        vo.setVisitRecordSwitch(userInfo.getIsShowVisitor());
        vo.setPersonalRecommendSwitch(userInfo.getIsOpenPersonalRecommend());

        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void switchPrivacy(Long uid, SwitchPrivacyDTO switchPrivacyDTO) {
        HeroUserInfo userInfoUpdate = new HeroUserInfo();
        userInfoUpdate.setIsShowVisitor(switchPrivacyDTO.getVisitRecordSwitch());
        if (Objects.nonNull(switchPrivacyDTO.getPersonalRecommendSwitch())) {
            userInfoUpdate.setIsOpenPersonalRecommend(switchPrivacyDTO.getPersonalRecommendSwitch());
        }
        heroUserInfoService.updateByUid(uid, userInfoUpdate);

        //如果是关闭【展示访客记录】，清空别人访问自己的访问记录
        userVisitRecordService.clearVisitRecord(uid);
    }

    @Override
    public PageResultWrapper<UserListItemVO> pagePrivacyUser(Long fromUid, Integer privacyType, BasePageQueryDTO basePageQueryDTO) {
        PageInfo<HeroUserPrivacySetup> pageInfo = PageHelper.startPage(basePageQueryDTO.getPageNum(), basePageQueryDTO.getPageSize())
            .doSelectPageInfo(() -> this.listByUidAndPrivacyType(fromUid, privacyType));
        List<HeroUserPrivacySetup> privacySetups = pageInfo.getList();
        if (CollectionUtils.isEmpty(privacySetups)) {
            return PageResultWrapper.empty(basePageQueryDTO);
        }

        //装配用户信息
        List<Long> toUids = privacySetups.stream().map(HeroUserPrivacySetup::getToUid).distinct().collect(Collectors.toList());
        List<UserItemBriefVO> userItems = userService.buildUserItem(fromUid, toUids, true, true);
        Map<Long, UserItemBriefVO> uidUserMap =
            userItems.stream().collect(Collectors.toMap(UserItemBriefVO::getUid, Function.identity()));

        List<UserListItemVO> voList =
            privacySetups.stream()
                .map(privacySetup -> this.convertUserListItemVO(privacySetup, uidUserMap))
                .collect(Collectors.toList());

        return PageResultWrapper.wrapper(pageInfo.getTotal(), voList, pageInfo.isHasNextPage(), basePageQueryDTO);
    }

    @Override
    public List<HeroUserPrivacySetup> listByUidAndPrivacyType(Long fromUid, Integer privacyType) {
        HeroUserPrivacySetup query = new HeroUserPrivacySetup();
        query.setFromUid(fromUid);
        query.setPrivacyType(privacyType);
        query.setState(StateEnum.EFFECTIVE.getCode());
        return this.getBaseMapper().select(query);
    }

    @Override
    public List<HeroUserPrivacySetup> listByToUidAndPrivacyType(Long toUid, Integer privacyType) {
        HeroUserPrivacySetup query = new HeroUserPrivacySetup();
        query.setToUid(toUid);
        query.setPrivacyType(privacyType);
        query.setState(StateEnum.EFFECTIVE.getCode());
        return this.getBaseMapper().select(query);
    }

    private HeroUserPrivacySetup buildEntity(Long fromUid, Long toUid, Integer privacyType) {
        HeroUserPrivacySetup entity = new HeroUserPrivacySetup();
        entity.setFromUid(fromUid);
        entity.setToUid(toUid);
        entity.setPrivacyType(privacyType);
        entity.setState(StateEnum.EFFECTIVE.getCode());
        entity.setCreateBy(fromUid);
        entity.setUpdateBy(fromUid);
        return entity;
    }

    private UserListItemVO convertUserListItemVO(HeroUserPrivacySetup privacySetup, Map<Long, UserItemBriefVO> uidUserMap) {
        Long uid = privacySetup.getToUid();
        UserListItemVO vo = new UserListItemVO();

        vo.setId(privacySetup.getId())
            .setSwitchState(NumConsts.ONE)
            .setUserInfo(uidUserMap.get(uid));
        vo.setCreateTime(privacySetup.getCreateTime());

        return vo;
    }
}